package com.bocloud.cmp.service.resource;

import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.cmp.dao.CloudServerDao;
import com.bocloud.cmp.dao.CloudVendorDao;
import com.bocloud.cmp.dao.ClusterDao;
import com.bocloud.cmp.dao.HostSystemDao;
import com.bocloud.cmp.dao.NetworkCardDao;
import com.bocloud.cmp.dao.NetworkDao;
import com.bocloud.cmp.dao.RegionDao;
import com.bocloud.cmp.dao.SnapshotDao;
import com.bocloud.cmp.dao.SubnetDao;
import com.bocloud.cmp.driver.providers.intf.NetworkProvider;
import com.bocloud.cmp.entity.resource.CloudServer;
import com.bocloud.cmp.entity.resource.CloudVendor;
import com.bocloud.cmp.entity.resource.Cluster;
import com.bocloud.cmp.entity.resource.HostSystem;
import com.bocloud.cmp.entity.resource.Network;
import com.bocloud.cmp.entity.resource.NetworkCard;
import com.bocloud.cmp.entity.resource.Region;
import com.bocloud.cmp.entity.resource.Snapshot;
import com.bocloud.cmp.entity.resource.Subnet;
import com.bocloud.cmp.enums.VMStatus;
import com.bocloud.cmp.enums.VendorType;
import com.bocloud.cmp.interfaces.resource.NetworkService;
import com.bocloud.cmp.model.NetBean;
import com.bocloud.cmp.model.NetworkModel;
import com.bocloud.cmp.model.SwitchModel;
import com.bocloud.common.model.BsmResult;
import com.bocloud.common.model.GridBean;
import com.bocloud.common.model.Param;
import com.bocloud.common.model.SimpleBean;
import com.bocloud.common.utils.Common;
import com.bocloud.common.utils.GridHelper;
import com.bocloud.common.utils.JSONTools;
import com.bocloud.common.utils.MapTools;
import com.bocloud.coordinator.harmony.HarmonyLock;
import com.bocloud.coordinator.harmony.LockFactory;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;

/**
 * 网络Service接口实现
 * 
 * @author dongkai
 *
 */
@Service("networkService")
public class NetworkServiceImpl implements NetworkService {

	private static Logger logger = LoggerFactory.getLogger(ImageServiceImpl.class);
	@Autowired
	private LockFactory lockFactory;
	@Autowired
	private NetworkDao networkDao;
	@Autowired
	private CloudVendorDao cloudVendorDao;
	@Autowired
	private RegionDao regionDao;
	@Autowired
	private SubnetDao subnetDao;
	@Autowired
	private HostSystemDao hostSystemDao;
	@Autowired
	private NetworkCardDao networkCardDao;
	@Autowired
	private CloudServerDao cloudServerDao;
	@Autowired
	private ClusterDao clusterDao;
	@Autowired
	private SnapshotDao snapshotDao;
	@Autowired
	private NetworkProvider networkProvider;

	@Override
	public BsmResult list(int page, int rows, List<Param> params, Map<String, String> sorter, Boolean simple) {
		List<Network> list = null;
		List<SimpleBean> beans = null;
		int total = 0;
		GridBean gridBean = null;
		try {
			if (null == sorter) {
				sorter = Maps.newHashMap();
			}
			sorter.put("gmtCreate", Common.ONE);
			total = networkDao.count(params);
			if (simple) {
				beans = networkDao.list(params, sorter);
				gridBean = new GridBean(1, 1, total, beans);
			} else {
				list = networkDao.list(page, rows, params, sorter);
				for (Network network : list) {
					Region region = regionDao.query(network.getRegion());
					if (null != region) {
						network.setRegionName(region.getName());
					}
					CloudVendor cloudVendor = cloudVendorDao.query(network.getVendorId());
					if (null != cloudVendor) {
						network.setVendorName(cloudVendor.getName());
					}
				}
				gridBean = GridHelper.getBean(page, rows, total, list);
			}
			return new BsmResult(true, gridBean, "查询成功");
		} catch (Exception e) {
			logger.error("list network failure:", e);
			return new BsmResult(false, "查询失败", null, null);
		}
	}

	@Override
	public BsmResult create(String params, Long userId) {
		JSONObject object = JSONTools.isJSONObj(params);
		Long id = object.getLong(Common.ID);
		Long region = object.getLong(Common.REGION);
		String name = object.getString(Common.NAME);
		Region reg = null;
		BsmResult bsmResult = null;
		try {
			CloudVendor cloudVendor = cloudVendorDao.query(id);
			if (null == cloudVendor) {
				logger.error("get cloudVendor failure!");
				return new BsmResult(false, "创建失败!");
			}
			Map<String, Object> param = MapTools.simpleMap("name", name);
			if (!VendorType.OPENSTACK.name().equals(cloudVendor.getType())) {
				reg = regionDao.query(region);
				if (null == reg) {
					logger.error("get region failure!");
					return new BsmResult(false, "创建失败!");
				}
			} else {
				String type = object.getString("type");
				String phyNetwork = null;
				String segmentationId = null;
				if (object.containsKey("phyNetwork")) {
					phyNetwork = object.getString("phyNetwork");
				}
				if (object.containsKey("segmentationId")) {
					segmentationId = object.getString("segmentationId");
				}
				Boolean adminStateup = object.getBoolean("adminStateup");
				Boolean shared = object.getBoolean("shared");
				Boolean isRouterExternal = object.getBoolean("isRouterExternal");
				param.put("type", type);
				if (null != phyNetwork) {
					param.put("phyNetwork", phyNetwork);
				}
				if (null != segmentationId) {
					param.put("segmentationId", segmentationId);
				}
				param.put("adminStateup", adminStateup);
				param.put("shared", shared);
				param.put("isRouterExternal", isRouterExternal);
			}
			NetworkModel model = JSONObject.parseObject(JSONObject.toJSONString(param), NetworkModel.class);
			if (null == reg) {
				bsmResult = networkProvider.create(cloudVendor.getUuid(), null, model);
			} else {
				bsmResult = networkProvider.create(cloudVendor.getUuid(), reg.getCode(), model);
			}
			if (null == bsmResult || !bsmResult.isSuccess()) {
				return new BsmResult(false, "创建失败!");
			}
			Network network = JSONObject.parseObject(JSONObject.toJSONString(bsmResult.getData()), Network.class);
			String status = null;
			if (network.getStatus().equalsIgnoreCase("ACTIVE")) {
				status = VMStatus.RUNNING.name();
			} else {
				status = VMStatus.EXCEPTION.name();
			}
			network.setVendorId(id);
			network.setStatus(status);
			network.setRegion(region);
			network.setCreaterId(userId);
			networkDao.save(network);
			return new BsmResult(true, "创建成功!");
		} catch (Exception e) {
			logger.error("create network failure:", e);
			return new BsmResult(false, "创建失败!");
		}
	}

	@Override
	public BsmResult remove(Long id, Long userId) {
		String path = Network.class.getSimpleName() + "_" + id;
		HarmonyLock lock = null;
		Boolean result = false;
		BsmResult bsmResult = null;
		try {
			lock = lockFactory.getLock(path);
			if (!lock.acquire(path, 10, TimeUnit.SECONDS)) {
				logger.warn("Get harmonyLock time out!");
				return new BsmResult(false, "请求超时", "", "");
			}
			Network network = networkDao.query(id);
			if (null == network) {
				logger.warn("network data not exist");
				return new BsmResult(false, "数据不存在", "", "");
			}
			String networkId = network.getNetworkId();
			List<Subnet> subnets = subnetDao.list(network.getVendorId(), networkId);
			if (!subnets.isEmpty()) {
				logger.warn("subnets is not null");
				return new BsmResult(false, "此网络存在子网，无法删除!");
			}
			// 云供应商
			CloudVendor cloudVendor = cloudVendorDao.query(network.getVendorId());
			Region region = regionDao.query(network.getRegion());
			if (null == cloudVendor) {
				logger.error("get cloudVendor failure");
				return new BsmResult(false, "删除失败", "", "");
			}

			if (VendorType.OPENSTACK.name().equals(cloudVendor.getType())) {
				bsmResult = networkProvider.remove(networkId, cloudVendor.getUuid(), null);
			} else {
				if (null == region) {
					logger.error("get region failure");
					return new BsmResult(false, "删除失败", "", "");
				}
				bsmResult = networkProvider.remove(networkId, cloudVendor.getUuid(), region.getCode());
			}

			if (null == bsmResult || !bsmResult.isSuccess()) {
				return new BsmResult(false, "删除失败");
			}
			result = networkDao.remove(id, userId);
		} catch (Exception e) {
			logger.error("remove network fail:", e);
			return new BsmResult(false, "删除失败", "", "");
		} finally {
			if (null != lock) {
				lock.release();
			}
		}
		return result ? new BsmResult(true, "删除成功") : new BsmResult(false, "删除失败", "", "");
	}

	@Override
	public BsmResult detail(Long id) {
		try {
			Network network = networkDao.query(id);
			CloudVendor vendor = cloudVendorDao.query(network.getVendorId());
			if (null != vendor) {
				network.setVendorName(vendor.getName());
			}
			return new BsmResult(true, network, "查询详情成功!");
		} catch (Exception e) {
			logger.error("query network detail failure:", e);
			return new BsmResult(false, "查询详情失败!");
		}
	}

	@Override
	public BsmResult modify(NetBean bean, Long userId) {
		String path = Network.class.getSimpleName() + "_" + bean.getId();
		HarmonyLock lock = null;
		Region region = null;
		BsmResult bsmResult = null;
		try {
			lock = lockFactory.getLock(path);
			if (!lock.acquire(path, 10, TimeUnit.SECONDS)) {
				logger.warn("Get harmonyLock time out!");
				return new BsmResult(false, "请求超时");
			}
			Network network = networkDao.query(bean.getId());
			if (null == network) {
				logger.warn("network data not exist");
				return new BsmResult(false, "数据不存在");
			}
			// 云供应商
			CloudVendor cloudVendor = cloudVendorDao.query(network.getVendorId());
			if (null == cloudVendor) {
				logger.error("get cloudVendor failure");
				return new BsmResult(false, "修改失败", "", "");
			}
			BeanUtils.copyProperties(bean, network);
			NetworkModel model = JSONObject.parseObject(JSONObject.toJSONString(network), NetworkModel.class);
			if (!VendorType.OPENSTACK.name().equals(cloudVendor.getType())) {
				region = regionDao.query(network.getRegion());
				if (null == region) {
					logger.error("get region failure");
					return new BsmResult(false, "修改失败", "", "");
				}
				bsmResult = networkProvider.modify(cloudVendor.getUuid(), region.getCode(), model);
			} else {
				bsmResult = networkProvider.modify(cloudVendor.getUuid(), null, model);
			}
			if (null == bsmResult || !bsmResult.isSuccess()) {
				return new BsmResult(false, "修改失败");
			}
			network.setName(bean.getName());
			networkDao.update(network);
			return new BsmResult(true, network, "修改网络成功");
		} catch (Exception e) {
			logger.error("modify network fail:", e);
			return new BsmResult(false, "修改网络失败");
		} finally {
			if (null != lock) {
				lock.release();
			}
		}
	}

	@Override
	public BsmResult createDSwitch(SwitchModel model, Long userId) {
		try {
			CloudVendor cloudVendor = cloudVendorDao.query(model.getVendorId());
			if (null == cloudVendor) {
				logger.error("get cloudVendor and region failure");
				return new BsmResult(false, "未获取到云供应商");
			}
			Map<Long, List<Long>> hosts = model.getHosts();
			Map<String, List<String>> values = Maps.newHashMap();
			List<NetworkCard> networkCards = Lists.newArrayList();
			// 获取宿主机名称和网卡名称
			for (Long hostId : hosts.keySet()) {
				List<Long> cardIds = hosts.get(hostId);
				List<String> cards = Lists.newArrayList();
				for (Long cardId : cardIds) {
					NetworkCard card = this.networkCardDao.query(cardId);
					cards.add(card.getName());
					networkCards.add(card);
				}
				HostSystem host = this.hostSystemDao.query(hostId);
				values.put(host.getName(), cards);
			}
			model.setValues(values);
			// 创建交换机
			BsmResult result = networkProvider.createDSwitch(cloudVendor.getUuid(), model);
			// 创建成功则更新网卡为已使用
			if (result.isSuccess()) {
				for (NetworkCard card : networkCards) {
					card.setUsed(true);
					card.setMenderId(userId);
					networkCardDao.update(card);
				}
				List<Network> networks = this.networkDao.listByVdc(model.getVdcId());
				Map<String, Network> maps = Maps.newHashMap();
				for (Network network : networks) {
					maps.put(network.getNetworkVal(), network);
				}
				// 同步数据中心
				String content = JSONObject.toJSONString(result.getData());
				List<Network> nets = JSONObject.parseArray(content, Network.class);
				for (Network network : nets) {
					if (!maps.containsKey(network.getNetworkVal())) {
						network.setVendorId(model.getVendorId());
						network.setCreaterId(userId);
						network.setMenderId(userId);
						network.setVdcId(model.getVdcId());
						this.networkDao.save(network);
					}
				}
			}
			return new BsmResult(result.isSuccess(), result.getMessage());
		} catch (Exception e) {
			logger.error("exception info", e);
			return new BsmResult(false, "创建分布式交换机失败");
		}
	}

	@Override
	public BsmResult servers(Long id) {
		try {
			List<CloudServer> servers = this.cloudServerDao.listByNetwork(id);
			for (CloudServer server : servers) {
				// 设置主机名称
				HostSystem hostSystem = hostSystemDao.query(server.getHostId());
				if (null != hostSystem) {
					server.setHostName(hostSystem.getName());
					// 设置集群名称
					if (null != hostSystem.getClusterId()) {
						Cluster cluster = clusterDao.query(hostSystem.getClusterId());
						if (null != cluster) {
							server.setClusterName(cluster.getName());
						}
					}
				}
				// 设置快照数量
				List<Snapshot> snapshots = snapshotDao.listByVMid(server.getId());
				server.setSnapshotCount(snapshots.size());
			}
			return new BsmResult(true, servers, "查询虚拟机成功");
		} catch (Exception e) {
			logger.error("List cloudServer error：", e);
			return new BsmResult(false, "查询虚拟机失败");
		}
	}

}
